/*
 *  Copyright (C) 2009 takaji
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * StartPage.java
 *
 * Created on Dec 22, 2009, 9:20:47 PM
 */
package dakside.hacc;

import dakside.hacc.core.config.Configuration;
import org.dakside.dao.ConnectionInfo;
import org.dakside.dao.DAOException;
import dakside.hacc.core.dao.DAOFactory;
import org.dakside.exceptions.ArgumentException;
import org.dakside.duck.helpers.SwingHelper;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.event.EventListenerList;
import org.dakside.duck.plugins.AppCentral;
import org.dakside.duck.plugins.FunctionGroup;
import org.dakside.duck.plugins.FunctionPool;
import org.jdesktop.application.Action;

/**
 * Start page
 *
 * @author Takaji
 */
public class StartPage extends javax.swing.JPanel {

    private static final Logger logger = Logger.getLogger(StartPage.class.getName());
    
    protected EventListenerList activationListener = new EventListenerList();

    public void addActiveStateChangedListener(ActionListener l) {
        activationListener.add(ActionListener.class, l);
    }

    public void removeActiveStateChangedListener(ActionListener l) {
        activationListener.remove(ActionListener.class, l);
    }

    private void fireActiveStateChanged(ActionEvent e) {
        if (e == null) {
            e = new ActionEvent(this, 0, "");
        }
        Object[] listeners = activationListener.getListenerList();
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == ActionListener.class) {
                ((ActionListener) listeners[i + 1]).actionPerformed(e);
            }
        }
    }

    public boolean isActivated() {
        return btnUnload.isEnabled();
    }

    /**
     * Creates new form StartPage
     */
    public StartPage() {
        initComponents();

        // TODO: Replace this hardcode Function Group priorities
        FunctionGroup.Priority[] priorities = new FunctionGroup.Priority[]{
            new FunctionGroup.Priority("Transactions", 0),
            new FunctionGroup.Priority("Accounting", 10),
            new FunctionGroup.Priority("Financial", 20),
            new FunctionGroup.Priority("Reports", 30),
            new FunctionGroup.Priority("Import/Export", 40),
            new FunctionGroup.Priority("Configuration", 50)
        };
        this.groupModulePanel1.load(priorities);

        //set default database path
        String defaultPath = Configuration.getInstance().getLastDatabaseFile();
        txtDBPath.setText(defaultPath);

        //deactivate all modules by default
        groupModulePanel1.deactivate();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        dbTypeGroup = new javax.swing.ButtonGroup();
        jLabel1 = new javax.swing.JLabel();
        txtDBPath = new javax.swing.JTextField();
        btnOpen = new javax.swing.JButton();
        btnCreate = new javax.swing.JButton();
        btnLoad = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();
        rbDB4O = new javax.swing.JRadioButton();
        jRadioButton1 = new javax.swing.JRadioButton();
        jRadioButton2 = new javax.swing.JRadioButton();
        btnUnload = new javax.swing.JButton();
        groupModulePanel1 = new org.dakside.duck.appui.GroupModulePanel();

        setName("Form"); // NOI18N

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(dakside.hacc.HaccApp.class).getContext().getResourceMap(StartPage.class);
        jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N
        jLabel1.setName("jLabel1"); // NOI18N

        txtDBPath.setText(resourceMap.getString("txtDBPath.text")); // NOI18N
        txtDBPath.setName("txtDBPath"); // NOI18N

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(dakside.hacc.HaccApp.class).getContext().getActionMap(StartPage.class, this);
        btnOpen.setAction(actionMap.get("selectDBFile")); // NOI18N
        btnOpen.setText(resourceMap.getString("btnOpen.text")); // NOI18N
        btnOpen.setName("btnOpen"); // NOI18N

        btnCreate.setAction(actionMap.get("createDBFile")); // NOI18N
        btnCreate.setText(resourceMap.getString("btnCreate.text")); // NOI18N
        btnCreate.setName("btnCreate"); // NOI18N

        btnLoad.setAction(actionMap.get("loadDB")); // NOI18N
        btnLoad.setText(resourceMap.getString("btnLoad.text")); // NOI18N
        btnLoad.setName("btnLoad"); // NOI18N

        jLabel2.setText(resourceMap.getString("jLabel2.text")); // NOI18N
        jLabel2.setName("jLabel2"); // NOI18N

        dbTypeGroup.add(rbDB4O);
        rbDB4O.setSelected(true);
        rbDB4O.setText(resourceMap.getString("rbDB4O.text")); // NOI18N
        rbDB4O.setName("rbDB4O"); // NOI18N

        dbTypeGroup.add(jRadioButton1);
        jRadioButton1.setText(resourceMap.getString("jRadioButton1.text")); // NOI18N
        jRadioButton1.setEnabled(false);
        jRadioButton1.setName("jRadioButton1"); // NOI18N

        dbTypeGroup.add(jRadioButton2);
        jRadioButton2.setText(resourceMap.getString("jRadioButton2.text")); // NOI18N
        jRadioButton2.setEnabled(false);
        jRadioButton2.setName("jRadioButton2"); // NOI18N

        btnUnload.setAction(actionMap.get("unloadDB")); // NOI18N
        btnUnload.setText(resourceMap.getString("btnUnload.text")); // NOI18N
        btnUnload.setEnabled(false);
        btnUnload.setName("btnUnload"); // NOI18N

        groupModulePanel1.setName("groupModulePanel1"); // NOI18N

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel1)
                    .addComponent(jLabel2))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(txtDBPath, javax.swing.GroupLayout.DEFAULT_SIZE, 309, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(rbDB4O)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jRadioButton1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jRadioButton2)
                        .addGap(53, 53, 53)))
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(btnLoad, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(btnCreate, javax.swing.GroupLayout.DEFAULT_SIZE, 63, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(btnUnload, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(btnOpen, javax.swing.GroupLayout.DEFAULT_SIZE, 73, Short.MAX_VALUE))
                .addContainerGap())
            .addComponent(groupModulePanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 546, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(txtDBPath, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(btnCreate)
                    .addComponent(btnOpen))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(rbDB4O)
                    .addComponent(jRadioButton1)
                    .addComponent(jRadioButton2)
                    .addComponent(btnLoad)
                    .addComponent(btnUnload))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(groupModulePanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 198, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    public File getCurrentFile() {
        try {
            File f = new File(txtDBPath.getText());
        } catch (Exception ex) {
        }
        return new File(Configuration.getInstance().getHomeDirectory());
    }

    @Action
    public void selectDBFile() {
        JFileChooser chooser = new JFileChooser(getCurrentFile());
        if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
            File filePath = chooser.getSelectedFile();
            txtDBPath.setText(filePath.getAbsolutePath());
        }
    }

    @Action
    public void createDBFile() {
        JFileChooser chooser = new JFileChooser(getCurrentFile());
        if (chooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
            File filePath = chooser.getSelectedFile();
            if (filePath.exists() && filePath.canWrite()) {
                //delete if exist
                //TODO enable localization via properties file
                int status = JOptionPane.showConfirmDialog(chooser,
                        "<html> Do you want to override this database file?<br/>This action cannot be undone.",
                        "Confirmation",
                        JOptionPane.YES_NO_OPTION);
                if (status == JOptionPane.YES_OPTION) {
                    filePath.delete();
                }
            }
            txtDBPath.setText(filePath.getAbsolutePath());
        }
    }

    @Action
    public void loadDB() {
        try {
            String dbPath = txtDBPath.getText();
            int dbType = DAOFactory.PGSQL_DATABASE;
            if (rbDB4O.isSelected()) {
                dbType = DAOFactory.DB4O_DATABASE;
            }
            Configuration.getInstance().setInfo(new ConnectionInfo(dbPath, dbType));
            if (Configuration.getInstance().getDAOFactory() != null) {
                //XXX can get DAO factory -> info correct
                groupModulePanel1.activate();
                //TODO can we do this smarter?
                btnLoad.setEnabled(false);
                btnOpen.setEnabled(false);
                btnCreate.setEnabled(false);
                txtDBPath.setEnabled(false);
                btnUnload.setEnabled(true);

                //save last database file
                Configuration.getInstance().saveLastDatabaseFile(dbPath);
                AppCentral.getAPIDelegate().setAppTitle(dbPath);
                fireActiveStateChanged(null);
            }
        } catch (DAOException ex) {
            logger.log(Level.SEVERE, null, ex);
            //XXX Localization
            Throwable t = ex.getCause();
            if (t != null && "com.db4o.ext.DatabaseFileLockedException".equals(t.getClass().getName())) {
                SwingHelper.alert("<html>Database file is locked<br/>"
                        + "Are you opening this database file in another session?",
                        "Database file is locked");
            }
        } catch (ArgumentException ex) {
            logger.log(Level.SEVERE, null, ex);
        }

    }

    @Action
    public void unloadDB() {
        //XXX notify user first
        int answer = JOptionPane.showConfirmDialog(null,
                "<html>Are you sure you want to close this working session?<br/>"
                + "All work haven't been saved will be discarded.",
                "Confirmation",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.WARNING_MESSAGE);

        if (answer == JOptionPane.NO_OPTION) {
            return;
        }

        //Try to shutdown database
        try {
            Configuration.getInstance().getDAOFactory().shutdown();
            Configuration.getInstance().setInfo(null);
        } catch (NullPointerException ex) {
            Logger.getLogger(StartPage.class.getName()).log(Level.SEVERE, null, ex);
        } catch (DAOException ex) {
            Logger.getLogger(StartPage.class.getName()).log(Level.SEVERE, null, ex);
        }

        groupModulePanel1.deactivate();
        //close all tab
        HaccView.getInstance().closeAllTabsButStartPage();

        //unload all modules
        FunctionPool.getInstance().unload();
        AppCentral.getAPIDelegate().setAppTitle("");

        //reset UI state
        btnLoad.setEnabled(true);
        btnOpen.setEnabled(true);
        btnCreate.setEnabled(true);
        txtDBPath.setEnabled(true);
        btnUnload.setEnabled(false);
        fireActiveStateChanged(null);
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnCreate;
    private javax.swing.JButton btnLoad;
    private javax.swing.JButton btnOpen;
    private javax.swing.JButton btnUnload;
    private javax.swing.ButtonGroup dbTypeGroup;
    private org.dakside.duck.appui.GroupModulePanel groupModulePanel1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JRadioButton jRadioButton1;
    private javax.swing.JRadioButton jRadioButton2;
    private javax.swing.JRadioButton rbDB4O;
    private javax.swing.JTextField txtDBPath;
    // End of variables declaration//GEN-END:variables
}
